#include "outils.h"

void cmatBords (char c, int lmin, int cmin, int lmax, int cmax, char** mat){
    /* Fait les bords d'une matrice de caractère avec un caractère */
    int eLigne;
    int eColonne;
    assert(lmax>=0);
    assert(cmax>=0);
    for(eColonne=cmin;eColonne<cmax;eColonne++) {
        mat[lmin][eColonne]=c;
        mat[lmax-1][eColonne]=c;
    }
    for(eLigne=lmin;eLigne<lmax;eLigne++) {
        mat[eLigne][cmin]=c;
        mat[eLigne][cmax-1]=c;
    }
}

void Alea0() {
    /* Permet de générer une nouvelle suite pseudo-aleatoire */
    srand((unsigned int)time(NULL));
}

void rLigne (){
    /* Fait un retour à la ligne */
    printf("\n");
}

void cmatInit (char c, int lmax, int cmax, char** mat){
    /* Initialise une matrice de caractère */
    int ligne;
    int colonne;
    assert(lmax>=0);
    assert(cmax>=0);
    for(ligne=0;ligne<lmax;ligne++){
        for(colonne=0;colonne<cmax;colonne++){
            mat[ligne][colonne]=c;
        }
    }
}

void ematInit (int e, int lmax, int cmax, int** mat){
    /* Initialise une matrice d'entier */
    int ligne;
    int colonne;
    assert(isdigit(e));
    assert(lmax>=0);
    assert(cmax>=0);
    for(ligne=0;ligne<lmax;ligne++){
        for(colonne=0;colonne<cmax;colonne++){
            mat[ligne][colonne]=e;
        }
    }
}

void eAfficher (int entier){
	/* Affiche un entier */
    	printf("%i",entier);
}

void cAfficher (char caractere){
	/* Affiche un caractère */
    	printf("%c",caractere);
}

void meAfficher (char *sMessage, int eA){
	/* Affiche une phrase et un entier */
    	printf("%s %i", sMessage, eA);
}

void mcAfficher (char *sMessage, char cA){
	/* Affiche une phrase et un caractère */
    	printf("%s %c", sMessage, cA);
}

void cmatAfficher (int lmin, int cmin, int lmax, int cmax, char** mat){
    /* Affiche une matrice de caractère */
    int ligne;
    int colonne;
    assert(lmax>=0);
    assert(cmax>=0);
    for(ligne=lmin;ligne<lmax;ligne++){
        for(colonne=cmin;colonne<cmax;colonne++){
            cAfficher(mat[ligne][colonne]);
            espaceAfficher();
            espaceAfficher();
        }
        rLigne();
    }
}

void ematAfficher (int lmax, int cmax, int** mat){
    /* Affiche une matrice de caractère */
    int ligne;
    int colonne;
    assert(lmax>=0);
    assert(cmax>=0);
    for(ligne=0;ligne<lmax;ligne++){
        for(colonne=0;colonne<cmax;colonne++){
            cAfficher(mat[ligne][colonne]);
            espaceAfficher();
            espaceAfficher();
        }
        rLigne();
    }
}

void espaceAfficher(){
	/* Affiche un espace */
   	printf(" ");
}

int bCroiss (int eAv, int eM, int eAp){
    /* Retourne vrai si eAv<=eM<=eAp */
    return ((eAv<=eM)&&(eM<=eAp));
}

int eEcrire (){
	/* Demande à l'utilisateur d'écrire un entier */
	int entier;
	do {
		entier=fgetc(stdin);
	}
	while(!isdigit(entier));
	return entier;
}

int cEcrire (){
	/* Demande à l'utilisateur d'écrire un caractère */
	char caractere;
	do {
		caractere=fgetc(stdin);
	}
	while(!isalpha(caractere));
	return caractere;
}

int eHasard (int tmin, int tmax){
    /* Prend un nombre aléatoire entre tmin et tmax */
    assert(tmin>=0);
    if(tmax==0&&tmin==0) tmax++; /* Préviens les bugs d'un tmin et tmax = 0 */
    assert(tmax>=tmin);
    return rand()%(tmax-tmin)+tmin;
}

int zHasard (int eLimite){
    /* Prend un nombre aléatoire entre 0 et eLimite */
    assert(eLimite>=0);
    return rand()%(eLimite-0);
}

int uHasard (int eMax){
    /* Prend un nombre aléatoire entre 1 et tmax */
    assert(eMax>=1);
    return rand()%(eMax-1)+1;
}

int epMottenonvide (t_motte** pMotte){
	/* Calcule et retourne le nombre de pMotte non vide */
	int eColonne, eLigne;
	int eMottenonvide=0;
	for(eLigne=1;eLigne<elmax;eLigne++){
		for(eColonne=1;eColonne<ecmax;eColonne++){
			if(pMotte[eLigne][eColonne].eEtatterre!=Rien&&pMotte[eLigne][eColonne].eEtatterre!=Pierre){
				eMottenonvide++;
			}
		}
	}
	return eMottenonvide;
}

void SDL_Ecrire(SDL_Surface* ecran, SDL_Surface *SDL_Texte, char* sTexte, int ePosX, int ePosY){
	/* Permet d'écrire un texte à un endroit précit en SDL */
	TTF_Font *police;
	SDL_Color couleurNoire = {0, 0, 0, 0}, couleurBlanche = {255, 255, 255, 0};
	SDL_Rect position;
	
	TTF_Init();
	
	police = TTF_OpenFont("arial.ttf", 12);

	SDL_FreeSurface(SDL_Texte);
	SDL_Texte = TTF_RenderUTF8_Shaded(police, sTexte, couleurNoire, couleurBlanche);
	position.x = ePosX;
	position.y = ePosY;
	SDL_BlitSurface(SDL_Texte, NULL, ecran, &position);

	TTF_CloseFont(police);
	TTF_Quit();
}

void SDL_Rect_Blanc(SDL_Surface* ecran, SDL_Surface *SDL_Clean, int eHauteur, int eLargeur, int ePosX, int ePosY){
	/* Permet de nettoyer un endroit d'une surface SDL en blanc */
	SDL_Rect position;
	SDL_Clean = SDL_CreateRGBSurface(SDL_HWSURFACE, eLargeur, eHauteur, 32, 0, 0, 0, 0);
	position.x = ePosX;
    	position.y = ePosY;
	SDL_FillRect(SDL_Clean, NULL, SDL_MapRGB(ecran->format, 255, 255, 255));
    	SDL_BlitSurface(SDL_Clean, NULL, ecran, &position);
}

void Rattaupe_Focus(SDL_Surface* ecran, t_rattaupes Rattaupe){
	/* S'occupe de rendre bleu le rattaupe qui doit jouer en SDL */
	SDL_Rect position;
	position.x = Rattaupe.ePosY * TAILLE_BLOC; /* Le SDL inverse ligne et colonne */
	position.y = Rattaupe.ePosX * TAILLE_BLOC;
	SDL_BlitSurface(IMG_Load("./images/focus.bmp"), NULL, ecran, &position);
}

void Envoyer_pMotte(t_motte** pMotte, int eNombreJoueur, int32_t eNombreJoueurPosition, int32_t eTour, SOCKET* csock){
	/* Permet l'envoie de la structure pMotte aux clients après sérialisation ainsi que la position du joueur qui joue et le nb de tours */
	int eLigne, eColonne;
	int eNombreJoueurIncremente;
	int32_t epMotteContenu[elmax][ecmax][4];
	int32_t eNombreJoueurPositiontemp = htonl(eNombreJoueurPosition);
	int32_t eTourtemp = htonl(eTour);

	/* Envoie de la structure pMotte */
	for(eNombreJoueurIncremente=1;eNombreJoueurIncremente<eNombreJoueur;eNombreJoueurIncremente++){
		for(eLigne=0;eLigne<elmax;eLigne++){
			for(eColonne=0;eColonne<ecmax;eColonne++){
				epMotteContenu[eLigne][eColonne][0]=htonl(pMotte[eLigne][eColonne].Nourriture);
				epMotteContenu[eLigne][eColonne][1]=htonl(pMotte[eLigne][eColonne].ptNourriture);
				epMotteContenu[eLigne][eColonne][2]=htonl(pMotte[eLigne][eColonne].eEtatterre);
				epMotteContenu[eLigne][eColonne][3]=htonl(pMotte[eLigne][eColonne].eTaupes);
			}
		}
		send(csock[eNombreJoueurIncremente], (char const*)epMotteContenu, sizeof(epMotteContenu), 0);
		send(csock[eNombreJoueurIncremente], (char const*)&eNombreJoueurPositiontemp, sizeof(eNombreJoueurPositiontemp), 0);
		send(csock[eNombreJoueurIncremente], (char const*)&eTourtemp, sizeof(eTourtemp), 0);
	}

}

void Recevoir_pMotte(t_motte** pMotte, int32_t eNombreJoueurIncremente, SOCKET* csock){
	/* Réception de la structure pMotte du client après qu'il ai joué */
	int eLigne, eColonne;
	int32_t epMotteContenu[elmax][ecmax][4];

	recv(csock[eNombreJoueurIncremente], (char *)epMotteContenu, sizeof(epMotteContenu), 0);
	usleep(200);
	/* Reception de la structure pMotte */
	for (eLigne = 0; eLigne < elmax; eLigne++){
		for(eColonne=0;eColonne<ecmax;eColonne++){
			pMotte[eLigne][eColonne].Nourriture = ntohl(epMotteContenu[eLigne][eColonne][0]);
			pMotte[eLigne][eColonne].ptNourriture = ntohl(epMotteContenu[eLigne][eColonne][1]);
			pMotte[eLigne][eColonne].eEtatterre = ntohl(epMotteContenu[eLigne][eColonne][2]);
			pMotte[eLigne][eColonne].eTaupes = ntohl(epMotteContenu[eLigne][eColonne][3]);
		}
	}
}

void Envoyer_pRattaupe(t_liste* pRattaupe, int32_t eNombreJoueurIncremente, SOCKET* csock){
	/* Envoie quand un joueur doit jouer sa liste sérialisée contenant chacune de ses rats-taupes */
	int32_t eNombreRattaupe=0;
	int32_t epRattaupeContenu[8];
	t_rattaupes Rattaupe;

	en_tete(pRattaupe);
	while(!hors_liste(pRattaupe)){
		eNombreRattaupe++;
		suivant(pRattaupe);
	}

	/* Envoie de la structure pRattaupe */
	eNombreRattaupe= htonl(eNombreRattaupe);
	send(csock[eNombreJoueurIncremente], (char const*)&eNombreRattaupe, sizeof(eNombreRattaupe), 0);
	en_queue(pRattaupe);
	while(!hors_liste(pRattaupe)){
		valeur_elt(pRattaupe,&Rattaupe);
		epRattaupeContenu[0]=htonl(Rattaupe.ePosX);
		epRattaupeContenu[1]=htonl(Rattaupe.ePosY);
		epRattaupeContenu[2]=htonl(Rattaupe.eSante);
		epRattaupeContenu[3]=htonl(Rattaupe.Sexe);
		epRattaupeContenu[4]=htonl(Rattaupe.Age);
		epRattaupeContenu[5]=htonl(Rattaupe.eGestation);
		epRattaupeContenu[6]=htonl(Rattaupe.eDelaiGrossesse);
		epRattaupeContenu[7]=htonl(Rattaupe.Race);
		send(csock[eNombreJoueurIncremente], (char const*)epRattaupeContenu, sizeof(epRattaupeContenu), 0);
		precedent(pRattaupe);
	}
}

void Recevoir_pRattaupe(t_liste* pRattaupe, int32_t eNombreJoueurIncremente, SOCKET* csock){
	/* Reçoit la liste de rat-taupe d'un joueur après qu'il ai joué */
	int32_t eNombreRattaupe=0;
	int32_t epRattaupeContenu[8];
	t_rattaupes Rattaupe;

	/* Reception de la structure pRattaupe */
	recv(csock[eNombreJoueurIncremente], (char *)&eNombreRattaupe, sizeof(eNombreRattaupe), 0);
	eNombreRattaupe=ntohl(eNombreRattaupe);
 	vider(pRattaupe);

	while(eNombreRattaupe>0){
		recv(csock[eNombreJoueurIncremente], (char *)epRattaupeContenu, sizeof(epRattaupeContenu), 0);
		Rattaupe.ePosX=ntohl(epRattaupeContenu[0]);
		Rattaupe.ePosY=ntohl(epRattaupeContenu[1]);
		Rattaupe.eSante=ntohl(epRattaupeContenu[2]);
		Rattaupe.Sexe=ntohl(epRattaupeContenu[3]);
		Rattaupe.Age=ntohl(epRattaupeContenu[4]);
		Rattaupe.eGestation=ntohl(epRattaupeContenu[5]);
		Rattaupe.eDelaiGrossesse=ntohl(epRattaupeContenu[6]);
		Rattaupe.Race=ntohl(epRattaupeContenu[7]);
		ajout_gauche(pRattaupe,Rattaupe);
		eNombreRattaupe--;
	}
}

void Proposer_Quitter_enjeu (int eNombreJoueur, t_motte** pMotte, t_liste** pRattaupe, int* classement, SDL_Surface* ecran, SOCKET* csock, SOCKET* csockfin){
	/* Menu proposant au joueur côté serveur de quitter, s'il accepte, indique aux clients que le jeu est fini et lance la fonction pour vider la mémoire */
	SDL_Surface *menu = NULL;
	SDL_Event event;
	SDL_Rect positionMenu;
	int continuer = 1;
	int eNombreJoueurIncremente;
	int32_t eJeufin=htonl(2);

	menu = IMG_Load("./images/quitter.jpg");
	positionMenu.x = 0;
	positionMenu.y = 0;

	SDL_BlitSurface(menu, NULL, ecran, &positionMenu);
	SDL_Flip(ecran);
	while (continuer)
	{
		SDL_WaitEvent(&event);
		switch(event.type)
		{
			case SDL_QUIT:
				SDL_FreeSurface(menu);
				for(eNombreJoueurIncremente=1;eNombreJoueurIncremente<eNombreJoueur;eNombreJoueurIncremente++){
					Envoyer_tour(0,eNombreJoueur,csock);
					send(csockfin[eNombreJoueurIncremente], (char const*)&eJeufin, sizeof(eJeufin), 0);
				}
				Quitter(eNombreJoueur,pMotte,pRattaupe,classement,csock,csockfin);
				SDL_Quit();
				exit(EXIT_SUCCESS);
				break;
			case SDL_KEYDOWN:
				switch(event.key.keysym.sym)
				{
					case SDLK_ESCAPE:
						continuer=0;
						break;
					case SDLK_F1:
						SDL_FreeSurface(menu);
						for(eNombreJoueurIncremente=1;eNombreJoueurIncremente<eNombreJoueur;eNombreJoueurIncremente++){
							Envoyer_tour(0,eNombreJoueur,csock);
							send(csockfin[eNombreJoueurIncremente], (char const*)&eJeufin, sizeof(eJeufin), 0);

						}
						Quitter(eNombreJoueur,pMotte,pRattaupe,classement,csock,csockfin);
						SDL_Quit();
						exit(EXIT_SUCCESS);
						break;
					case SDLK_F2:
						continuer=0;
						break;
					default:
						break;
				}
				break;
		}
	}
}

void Quitter (int eNombreJoueur, t_motte** pMotte, t_liste** pRattaupe, int* classement, SOCKET* csock, SOCKET* csockfin){
	/* Coupe les connexions et appel la fonction pour vider la mémoire */
	int eNombreJoueurIncremente;

	MemoireVider(pMotte,pRattaupe,eNombreJoueur,classement);

	for(eNombreJoueurIncremente=1;eNombreJoueurIncremente<eNombreJoueur;eNombreJoueurIncremente++){
		shutdown(csock[eNombreJoueurIncremente], 2);
		shutdown(csockfin[eNombreJoueurIncremente], 2);
	}
	close(*csock);
	close(*csockfin);
	free(csock);
	free(csockfin);
}

void MemoireVider(t_motte** pMotte, t_liste** pRattaupe, int32_t eNombreJoueur, int* classement){
	/* Vide la mémoire dynamique */
	int32_t eNombreJoueurIncremente;
	int eLigne;

	for(eNombreJoueurIncremente=0;eNombreJoueurIncremente<eNombreJoueur;eNombreJoueurIncremente++){
		free(pRattaupe[eNombreJoueurIncremente]);
	}

	for(eLigne=0;eLigne<elmax;eLigne++){
		free(pMotte[eLigne]);
	}
	free(pRattaupe);
	free(pMotte);
	free(classement);
}

void QuitterMenu(){
	/* Quitte le jeu lorsqu'il est encore au menu du début du jeu */
	SDL_Quit();
	exit(EXIT_SUCCESS);
}

void Envoyer_tour(int32_t eContinueJeu, int eNombre_joueur, SOCKET* csock){
	int32_t eJoueurincremente;
	eContinueJeu=htonl(eContinueJeu);
	for(eJoueurincremente=1;eJoueurincremente<eNombre_joueur;eJoueurincremente++){
		send(csock[eJoueurincremente], (char const*)&eContinueJeu, sizeof(eContinueJeu), 0);
	}
}

